package cn.edu.qfnu.oj.entity;

import cn.edu.qfnu.oj.entity.enums.State;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Entity
@DynamicUpdate
public class Task implements Serializable {

    private Integer id; //作业id
    private State state; //作业状态
    private String title; //作业标题
    private String content; // 作业内容
    private LocalDateTime startTime;  //开始时间
    private LocalDateTime endTime; //结束时间
    private String term; //学期
    private Teacher teacher; //创建作业的老师
    private Attend attend; //作业的参与记录 一对一关系
    
    private List<Submit> submits = new ArrayList<>();  //作业的提交记录一对多关系
    private Set<Classes> classes = new HashSet<>();  //作业分配的班级 多对多关系
    private Set<Problem> problems =  new HashSet<>();

    public Task() {}

    public Task(String title, String content, LocalDateTime startTime, LocalDateTime endTime, String term) {

        if (!LocalDateTime.now().isBefore(startTime) && !LocalDateTime.now().isAfter(endTime)) {
            this.state = State.UNDERWAY;
        } else if (LocalDateTime.now().isAfter(endTime)) {
            this.state = State.END;
        } else {
            this.state = State.NOT_START_YET;
        }
        this.title = title;
        this.content = content;
        this.startTime = startTime;
        this.endTime = endTime;
        this.term = term;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column
    @Enumerated(value = EnumType.STRING)
    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    @Column(length = 16)
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column(length = 128)
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Column(name = "start_time")
    public LocalDateTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }

    @Column(name = "end_time")
    public LocalDateTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }

    @Column(length = 16)
    public String getTerm() {
        return term;
    }

    public void setTerm(String term) {
        this.term = term;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass()) return false;

        Task task = (Task) o;

        return new EqualsBuilder()
                .append(id, task.id)
                .append(state, task.state)
                .append(title, task.title)
                .append(content, task.content)
                .append(startTime, task.startTime)
                .append(endTime, task.endTime)
                .append(term, task.term)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(id)
                .append(state)
                .append(title)
                .append(content)
                .append(startTime)
                .append(endTime)
                .append(term)
                .toHashCode();
    }

    //一个参与记录只对应一次作业，一次作业也只有一次参与记录
    //参与记录与作业是一对一关系
    @OneToOne(mappedBy = "task") // 作业与参与记录的一对多关系交给提交记录维护
    public Attend getAttend() {
        return attend;
    }

    public void setAttend(Attend attend) {
        this.attend = attend;
    }

    //一次作业有多个提交记录，而这多个提交记录只对应一次作业
    //因此作业与提交记录是一对多关系
    @OneToMany(mappedBy = "task") // 作业与提交记录的一对多关系交给提交记录维护
    public List<Submit> getSubmits() {
        return submits;
    }

    public void setSubmits(List<Submit> submitById) {
        this.submits = submitById;
    }


    //一次作业可被分配到多个班级，而这多个班级可以被分配到多个作业
    //所以作业与班级是多对多关系
    @ManyToMany // 维护作业与班级的多对多关系
    @JoinTable(name = "task_class",
            joinColumns = @JoinColumn(name = "task_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "class_id", referencedColumnName = "id"))
    public Set<Classes> getClasses() {
        return classes;
    }

    public void setClasses(Set<Classes> tasks) {
        this.classes = tasks;
    }

    //一次作业被一个老师创建，而一个老师可以创建多次作业
    //作业与老师是多对一关系
    @ManyToOne // 维护作业与老师的多对一关系
    @JoinColumn(name = "teacher_id", referencedColumnName = "teacher_id")
    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @ManyToMany
    @JoinTable(name = "submit",
            joinColumns = @JoinColumn(name = "task_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "problem_id", referencedColumnName = "id"))
    public Set<Problem> getProblems() {
        return problems;
    }

    public void setProblems(Set<Problem> problems) {
        this.problems = problems;
    }
}
